package com.shhic.hhplt.server.biz;

import java.util.LinkedList;
import java.util.List;

import com.shhic.hhplt.server.exceptions.CodeExhaustException;
import com.shhic.hhplt.server.model.SerialCode;

/**
 * 序列编码生成容器
 * @author 张文硕
 *
 */
public class SerialCodeGeneraterContainer implements ISerialCodeGeneraterContainer{
	
	public SerialCodeGeneraterContainer(SerialCode businessCode) {
		this.businessCode = businessCode;
		initSignList();
		initNowSign();
	}
	
	@Override
	public String getCodeName() {
		return businessCode.getCodeName();
	}
	
	private void initSignList(){
		String scheme = businessCode.getScheme();
		List<Sign> sl = new LinkedList<Sign>();
		for(int i=0;i<scheme.length();){
			if(scheme.charAt(i) == '$'){
				sl.add(new Sign(scheme.substring(i,i+=7)));
			}else{
				sl.add(new Sign(scheme.substring(i,i+=1)));
			}
		}
		signList = sl.toArray(new Sign[]{});
		
	}
	
	private void initNowSign(){
		if(businessCode.getNowCode() == null){
			businessCode.setNowCode(getNowCode());
		}else{
			for(int i=0;i<businessCode.getNowCode().length();i++){
				signList[i].setNow(businessCode.getNowCode().charAt(i));
			}
		}
	}
	
	
	
	private SerialCode businessCode;
	private Sign[] signList;
	int pointer = 0;
	private void generateNext() throws CodeExhaustException {
		if(pointer >= signList.length){
			if(businessCode.getIsCycle()==0)throw new CodeExhaustException();
			else {
				initSignList();
				pointer = 0;
				return;
			}
		}
		Sign s = signList[signList.length-pointer-1];
		try {
			s.next();
			pointer = 0;
		} catch (SchemeOverwileSpill e) {
			pointer++;
			generateNext();
		}
	}
	
	@Override
	public synchronized String getAndGenerateCode() throws CodeExhaustException {
		//先尝试使用已回收的编码
		if(!businessCode.getRetrievedCodeList().isEmpty()){
			return businessCode.getRetrievedCodeList().poll();
		}
		generateNext();
		businessCode.setNowCode(getNowCode());
		return businessCode.getNowCode();
	}

	@Override
	public String getAndGenerateCodeNoRetrieved() throws CodeExhaustException {
		generateNext();
		businessCode.setNowCode(getNowCode());
		return businessCode.getNowCode();
	}

	private String getNowCode(){
		StringBuilder sb = new StringBuilder();
		for(Sign s:signList){
			sb.append(s.getNow());
		}
		return sb.toString();
	}
	
	
	@Override
	public synchronized void retrieveCode(String code) {
		businessCode.getRetrievedCodeList().add(code);
	}
	
	private static class Sign{
		/**
		 * Scheme格式：$H[x-y]16进制符号，1-9-A-F；$D[0-9]10进制符号；$c[a-z]小写字母；$C[A-Z]大写字母
		 * 如果是静态的，则scheme为字符，不以$开头
		 * @param scheme
		 */
		public Sign(String scheme) {
			this.scheme = scheme;
			if(scheme.startsWith("$")){
				this.now = scheme.charAt(3);
			}else{
				isStatic = true;
				now = scheme.charAt(0);
			}
		}
		
		private String scheme;
		private char now;
		private boolean isStatic;	//静态（无模式）
		
		public char getNow() {
			return now;
		}
		public void setNow(char now) {
			this.now = now;
		}
		
		public void next()throws SchemeOverwileSpill{
			if(isStatic)throw new SchemeOverwileSpill();
			
			switch(scheme.charAt(1)){
			case 'H':	//16进制
				if(++now > scheme.charAt(5)){	//因为ASCII中，数字在前，字母在后，
					now = scheme.charAt(3);
					throw new SchemeOverwileSpill();
				}else if(now == 0x3a){
					//超过了0-9
					now = 'A';
				}
				break;
			default:	//其他
				if(++now > scheme.charAt(5)){
					now = scheme.charAt(3);
					throw new SchemeOverwileSpill();
				}
			}
		}
	}
	
	private static class SchemeOverwileSpill extends Exception{

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		
	}
	
	public static void main(String[] args) {
		SerialCode b = new SerialCode();
		b.setNowCode("ABCA0123");
//		b.setCycle(true);
		b.setScheme("ABC$H[0-A]$H[0-F]123");
		
		int i = 0;
		SerialCodeGeneraterContainer c = new SerialCodeGeneraterContainer(b);
			try {
				while(++i<500){
					System.out.println(c.getAndGenerateCode());
				}
			} catch (CodeExhaustException e) {
			}
	}
}
